<?php declare(strict_types=1);

namespace App\Bac\Handler\RBAC;

use App\Helper\RespHelper;
use Hyperf\DbConnection\Db;
use App\Bac\Model\RBAC\Admin;
use App\Bac\Model\RBAC\Permission;
use App\Exception\BusinessException;
use Hyperf\Di\Annotation\Inject;

class PermissionHandler
{

    use CacheManager;

    #[Inject]
    protected Permission $model;

    public function getList(): array
    {
        $query = $this->model::select(['*']);
        $rows = handleTreeList($query->get()->toArray());
        foreach ($rows as &$v1) {
            if (!(isset($v1['children']) && $v1['children']) && !$v1['parent_id']) {
                $v1['children'] = [];
            }
        }
        $total = count($rows);
        return compact("rows", "total");
    }

    public function addPermission(array $data): bool
    {
        $data['created_at'] = date('Y-m-d H:i:s', time());
        if ($this->model->where('name', $data['name'])->exists())
            throw new BusinessException(RespHelper::CODE_FAIL, "标识已经存在");
        $data['path_uri'] = trim($data['path_uri']);
        return $this->model->insert($data);
    }

    public function editPermission(int $id, array $data): bool
    {
        $info = $this->model->find($id);
        if (!$info)
            throw new BusinessException(RespHelper::CODE_FAIL, "权限不存在");
        if (!empty($data['parent_id'])) $info->parent_id = $data['parent_id'];
        if (!empty($data['name'])) $info->name = $data['name'];
        if (!empty($data['path_uri'])) $info->path_uri = trim($data['path_uri']);
        if (!empty($data['method'])) $info->method = $data['method'];
        if (isset($data['description'])) $info->description = trim($data['description']);
        if (!empty($data['order'])) $info->order = $data['order'];
        $saved = $info->save();
        $saved && $this->clearPermissionRelationCache($info->id);
        return $saved;
    }

    /**
     * 删除权限
     * @param int $id
     * @return int
     */
    public function delPermission(int $id): int
    {
        if ($this->model->where('parent_id', $id)->exists()) {
            throw new BusinessException(RespHelper::CODE_FAIL, "请先删除子权限");
        }
        $deleted = $this->model->destroy($id);
        $deleted && $this->clearPermissionRelationCache($id);
        return $deleted;
    }

    /**
     * 树型列表
     * @return array
     */
    public function treeList(): array
    {
        $list = $this->model->all()->toArray();
        if (!$list)
            return [];
        $tree = handleTreeList($list);
        foreach ($tree as &$v1) {
            if (!(isset($v1['children']) && $v1['children']) && !$v1['parent_id']) {
                $v1['children'] = [];
            }
        }
        return $tree;
    }

    /**
     * 获取用户权限
     * @param int $uid
     * @param int $super
     * @return string[]
     * @throws \RedisException
     */
    public function getUserPermissions(int $uid, int $super = 0): array
    {
        $cacheKey = Admin::getRbacCacheKey($uid);
        $redisInstance = getRedis();
        $listJson = $redisInstance->get($cacheKey);
        if ($listJson) {
            return json_decode($listJson, true);
        }
        if (!$super) {
            $list = ['admin'];
        } else {
            $prefix = env('DB_PREFIX', '');
            $list = Db::table('rbac_permissions')
                ->select([Db::raw("CONCAT({$prefix}rbac_permissions.path_uri,{$prefix}rbac_permissions.method) as path_uri")])
                ->join('rbac_role_permission', 'rbac_permissions.id', '=', 'rbac_role_permission.pms_id')
                ->join('rbac_role_admin', 'rbac_role_permission.role_id', '=', 'rbac_role_admin.role_id')
                ->where('rbac_role_admin.uid', '=', $uid)
                ->pluck('path_uri')
                ->toArray();
        }
        $redisInstance->set($cacheKey, json_encode($list), 3600 - rand(100, 999));
        return $list;
    }
}
